package jmine.tec.hydra.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import jmine.tec.hydra.HydraController;
import jmine.tec.hydra.HydraMessages;
import jmine.tec.hydra.exception.HydraException;
import jmine.tec.hydra.receive.HydraMessageInfo;
import jmine.tec.hydra.script.ReceiveActivationScriptContext;
import jmine.tec.hydra.script.SendActivationScriptContext;
import jmine.tec.persist.annotation.Alias;
import jmine.tec.persist.annotation.Index;
import jmine.tec.persist.annotation.UniqueConstraint;
import jmine.tec.script.ScriptExecutorException;
import jmine.tec.script.persistent.domain.Script;
import bancosys.tec.component.Documentation;
import bancosys.tec.persist.bussobj.PersistableBusinessObject;
import bancosys.tec.persist.persister.annotation.NaturalKey;

/**
 * Representa uma ativação do hydra. Através dessa ativação é possível decobrir quais ações de envio/recebimento devem ser executadas.
 * 
 * @author piercio
 */
@Entity
@Table(name = "HYDRA_ACTIVATION")
@Alias("HYDACT")
@SequenceGenerator(name = "SEQ_HYDACT", sequenceName = "SEQ_HYDACT")
@Documentation("ARMAZENA OS REGISTROS DE ATIVACAO DO HYDRA.")
public class HydraActivation extends PersistableBusinessObject {

    private Long id;

    private String mnemonico;

    private HydraSystem system;

    private Script activationScript;

    /**
     * @return o id da ativação.
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_HYDACT")
    @Column(name = "COD_HYDRA_ACTIVATION", nullable = false)
    @Documentation("CODIGO DA ATIVACAO DE INTEGRACAO.")
    public Long getId() {
        return this.id;
    }

    /**
     * @param id o valor do id da ativação.
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @return o mnemonico da ativação.
     */
    @NaturalKey
    @UniqueConstraint(name = "AK_HYDACT_0")
    @Column(name = "MNE_HYDRA_ACTIVATION", nullable = false)
    @Documentation("MNEMONICO DA ATIVACAO.")
    public String getMnemonico() {
        return this.mnemonico;
    }

    /**
     * @param mnemonico o valor do mnemonico da ativação.
     */
    public void setMnemonico(String mnemonico) {
        this.mnemonico = mnemonico;
    }

    /**
     * @return the system
     */
    @Index(suffix = "JT_1")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "COD_HYDRA_SYSTEM", nullable = false)
    @Documentation("CODIGO DO SISTEMA HYDRA ASSOCIADO A ESTA ATIVACAO.")
    public HydraSystem getSystem() {
        return this.system;
    }

    /**
     * @param system the system to set
     */
    public void setSystem(HydraSystem system) {
        this.system = system;
    }

    /**
     * @return o script de ativação, responsável por definir quais ações deverão ser executadas.
     */
    @Index(suffix = "JT_0")
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "COD_HYDRA_SCRIPT_ACTIVATION", nullable = false)
    @Documentation("CODIGO DO SCRIPT DE ATIVACAO.")
    public Script getActivationScript() {
        return this.activationScript;
    }

    /**
     * @param activationScript o script de ativação.
     */
    public void setActivationScript(Script activationScript) {
        this.activationScript = activationScript;
    }

    /**
     * Devolve o resultado da execução do script de ativação para o objeto passado.
     * 
     * @param source a fonte de dados que o script usará na execução.
     * @return o resultado do script executado.
     */
    public HydraMessageInfo executeReceive(Object source) {
        try {
            return this.activationScript.createContext(ReceiveActivationScriptContext.class).prepare(source).dispatchExecution();
        } catch (ScriptExecutorException e) {
            throw new HydraException(HydraMessages.BSH_ACTIVATION.create(this.mnemonico), e);
        }
    }

    /**
     * Devolve o resultado da execução do script de ativação para o objeto passado.
     * 
     * @param source a fonte de dados que o script usará na execução.
     * @return o resultado do script executado.
     */
    public String executeSend(Object source) {
        try {
            return this.activationScript.createContext(SendActivationScriptContext.class).prepare(source).dispatchExecution().getAction();
        } catch (ScriptExecutorException e) {
            throw new HydraException(HydraMessages.BSH_ACTIVATION.create(this.mnemonico), e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transient
    public HydraController getController() {
        return (HydraController) super.getController();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return this.mnemonico;
    }
}
